package service

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"gitee.com/wangshh_123/cross-pay-go/src/database"
	"gitee.com/wangshh_123/cross-pay-go/src/models"
	"gorm.io/gorm"
)

type NotificationService struct {
	db *gorm.DB
}

func NewNotificationService() *NotificationService {
	return &NotificationService{
		db: database.DB,
	}
}

// CreateNotification 创建通知
func (s *NotificationService) CreateNotification(ctx context.Context, n *models.Notification) error {
	return s.db.WithContext(ctx).Create(n).Error
}

// ListNotifications 分页查询通知
func (s *NotificationService) ListNotifications(ctx context.Context, userID int64, page, pageSize int, readStatus string) ([]models.Notification, int64, error) {
	var list []models.Notification
	var total int64
	db := s.db.WithContext(ctx).Model(&models.Notification{}).Where("user_id = ?", userID)

	if readStatus != "" {
		db = db.Where("status = ?", readStatus)
	}

	db.Count(&total)
	offset := (page - 1) * pageSize
	err := db.Order("created_at desc").Limit(pageSize).Offset(offset).Find(&list).Error
	return list, total, err
}

// MarkAsRead 标记为已读
func (s *NotificationService) MarkAsRead(ctx context.Context, userID, notificationID int64) error {
	return s.db.WithContext(ctx).
		Model(&models.Notification{}).
		Where("id = ? AND user_id = ?", notificationID, userID).
		Updates(map[string]interface{}{
			"status":  "READ",
			"read_at": time.Now(),
		}).Error
}

// DeleteNotification 删除通知
func (s *NotificationService) DeleteNotification(ctx context.Context, userID, notificationID int64) error {
	return s.db.WithContext(ctx).
		Where("id = ? AND user_id = ?", notificationID, userID).
		Delete(&models.Notification{}).Error
}

// BatchDeleteNotification 批量删除通知
func (s *NotificationService) BatchDeleteNotification(ctx context.Context, userID int64, notificationIDs []int64) error {
	return s.db.WithContext(ctx).
		Where("user_id = ? AND id IN ?", userID, notificationIDs).
		Delete(&models.Notification{}).Error
}

// GetNotificationType 获取通知类型
func (s *NotificationService) GetNotificationType(ctx context.Context, typeID int64) (*models.NotificationType, error) {
	var notificationType models.NotificationType
	err := s.db.WithContext(ctx).First(&notificationType, typeID).Error
	if err != nil {
		return nil, err
	}
	return &notificationType, nil
}

// ListNotificationTypes 获取所有通知类型
func (s *NotificationService) ListNotificationTypes(ctx context.Context) ([]models.NotificationType, error) {
	var types []models.NotificationType
	err := s.db.WithContext(ctx).Find(&types).Error
	return types, err
}

// GetUnreadCount 获取未读通知数量
func (s *NotificationService) GetUnreadCount(ctx context.Context, userID int64) (int64, error) {
	var count int64
	err := s.db.WithContext(ctx).
		Model(&models.Notification{}).
		Where("user_id = ? AND status = ?", userID, "UNREAD").
		Count(&count).Error
	return count, err
}

// MarkAllAsRead 标记所有通知为已读
func (s *NotificationService) MarkAllAsRead(ctx context.Context, userID int64) error {
	return s.db.WithContext(ctx).
		Model(&models.Notification{}).
		Where("user_id = ? AND status = ?", userID, "UNREAD").
		Updates(map[string]interface{}{
			"status":  "READ",
			"read_at": time.Now(),
		}).Error
}

// GetNotificationByID 根据ID获取通知详情
func (s *NotificationService) GetNotificationByID(ctx context.Context, userID, notificationID int64) (*models.Notification, error) {
	var notification models.Notification
	err := s.db.WithContext(ctx).
		Where("id = ? AND user_id = ?", notificationID, userID).
		First(&notification).Error
	if err != nil {
		return nil, err
	}
	return &notification, nil
}

// GetNotificationTypeByCode 根据代码获取通知类型
func (s *NotificationService) GetNotificationTypeByCode(ctx context.Context, code string) (*models.NotificationType, error) {
	var notificationType models.NotificationType
	err := s.db.WithContext(ctx).Where("code = ?", code).First(&notificationType).Error
	if err != nil {
		return nil, err
	}
	return &notificationType, nil
}

// GetNotificationTypeByID 根据ID获取通知类型
func (s *NotificationService) GetNotificationTypeByID(ctx context.Context, id int64) (*models.NotificationType, error) {
	var notificationType models.NotificationType
	err := s.db.WithContext(ctx).First(&notificationType, id).Error
	if err != nil {
		return nil, err
	}
	return &notificationType, nil
}

// CreateNotificationType 创建通知类型
func (s *NotificationService) CreateNotificationType(ctx context.Context, notificationType *models.NotificationType) error {
	return s.db.WithContext(ctx).Create(notificationType).Error
}

// UpdateNotificationType 更新通知类型
func (s *NotificationService) UpdateNotificationType(ctx context.Context, notificationType *models.NotificationType) error {
	return s.db.WithContext(ctx).Save(notificationType).Error
}

// DeleteNotificationType 删除通知类型
func (s *NotificationService) DeleteNotificationType(ctx context.Context, id int64) error {
	return s.db.WithContext(ctx).Delete(&models.NotificationType{}, id).Error
}

// PublishCardNotification 发布卡片通知
func (s *NotificationService) PublishCardNotification(ctx context.Context, userID int64, title, content string, data map[string]interface{}) error {
	// 构建通知数据
	var notificationData []byte
	if data != nil {
		var err error
		notificationData, err = json.Marshal(data)
		if err != nil {
			return fmt.Errorf("序列化通知数据失败: %v", err)
		}
	}

	// 创建卡片通知
	notification := &models.Notification{
		UserID:  userID,
		TypeID:  2, // CARD 通知类型ID
		Title:   title,
		Content: content,
		Data:    models.JSON(notificationData),
		Status:  "UNREAD",
	}

	if err := s.CreateNotification(ctx, notification); err != nil {
		return fmt.Errorf("创建卡片通知失败: %v", err)
	}

	log.Printf("已为用户 %d 发布卡片通知: %s", userID, title)
	return nil
}

// PublishSystemNotification 发布系统通知
func (s *NotificationService) PublishSystemNotification(ctx context.Context, userID int64, title, content string, data map[string]interface{}) error {
	// 构建通知数据
	var notificationData []byte
	if data != nil {
		var err error
		notificationData, err = json.Marshal(data)
		if err != nil {
			return fmt.Errorf("序列化通知数据失败: %v", err)
		}
	}

	// 创建系统通知
	notification := &models.Notification{
		UserID:  userID,
		TypeID:  3, // 系统通知类型ID
		Title:   title,
		Content: content,
		Data:    models.JSON(notificationData),
		Status:  "UNREAD",
	}

	if err := s.CreateNotification(ctx, notification); err != nil {
		return fmt.Errorf("创建系统通知失败: %v", err)
	}

	log.Printf("已为用户 %d 发布系统通知: %s", userID, title)
	return nil
}

// PublishBatchNotification 批量发布通知
func (s *NotificationService) PublishBatchNotification(ctx context.Context, userIDs []int64, typeID int64, title, content string, data map[string]interface{}) error {
	// 构建通知数据
	var notificationData []byte
	if data != nil {
		var err error
		notificationData, err = json.Marshal(data)
		if err != nil {
			return fmt.Errorf("序列化通知数据失败: %v", err)
		}
	}

	// 批量创建通知
	notifications := make([]models.Notification, 0, len(userIDs))
	now := time.Now()

	for _, userID := range userIDs {
		notification := models.Notification{
			UserID:    userID,
			TypeID:    typeID,
			Title:     title,
			Content:   content,
			Data:      models.JSON(notificationData),
			Status:    "UNREAD",
			CreatedAt: now,
			UpdatedAt: now,
		}
		notifications = append(notifications, notification)
	}

	// 使用事务批量插入
	err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		if err := tx.CreateInBatches(notifications, 100).Error; err != nil {
			return fmt.Errorf("批量创建通知失败: %v", err)
		}
		return nil
	})

	if err != nil {
		return err
	}

	log.Printf("已为 %d 个用户批量发布通知: %s", len(userIDs), title)
	return nil
}

// PublishCardStatusNotification 发布卡片状态变更通知
func (s *NotificationService) PublishCardStatusNotification(ctx context.Context, userID int64, cardID, oldStatus, newStatus string, additionalData map[string]interface{}) error {
	title := "卡片状态更新"
	content := fmt.Sprintf("您的卡片 %s 状态已从 %s 更新为 %s", cardID, oldStatus, newStatus)

	data := map[string]interface{}{
		"card_id":    cardID,
		"old_status": oldStatus,
		"new_status": newStatus,
		"timestamp":  time.Now().Format("2006-01-02 15:04:05"),
	}

	// 合并额外数据
	if additionalData != nil {
		for k, v := range additionalData {
			data[k] = v
		}
	}

	return s.PublishCardNotification(ctx, userID, title, content, data)
}

// PublishCardTransactionNotification 发布卡片交易通知
func (s *NotificationService) PublishCardTransactionNotification(ctx context.Context, userID int64, cardID, transactionType, amount, currency string, additionalData map[string]interface{}) error {
	title := "卡片交易通知"
	content := fmt.Sprintf("您的卡片 %s 发生 %s 交易，金额：%s %s", cardID, transactionType, amount, currency)

	data := map[string]interface{}{
		"card_id":          cardID,
		"transaction_type": transactionType,
		"amount":           amount,
		"currency":         currency,
		"timestamp":        time.Now().Format("2006-01-02 15:04:05"),
	}

	// 合并额外数据
	if additionalData != nil {
		for k, v := range additionalData {
			data[k] = v
		}
	}

	return s.PublishCardNotification(ctx, userID, title, content, data)
}

// PublishSystemAlertNotification 发布系统警告通知
func (s *NotificationService) PublishSystemAlertNotification(ctx context.Context, userID int64, alertType, message string, additionalData map[string]interface{}) error {
	title := "系统警告"
	content := fmt.Sprintf("系统检测到 %s：%s", alertType, message)

	data := map[string]interface{}{
		"alert_type": alertType,
		"message":    message,
		"timestamp":  time.Now().Format("2006-01-02 15:04:05"),
	}

	// 合并额外数据
	if additionalData != nil {
		for k, v := range additionalData {
			data[k] = v
		}
	}

	return s.PublishSystemNotification(ctx, userID, title, content, data)
}

// PublishBalanceChangeNotification 发布余额变更通知
func (s *NotificationService) PublishBalanceChangeNotification(ctx context.Context, userID int64, changeType, amount, currency, newBalance string, additionalData map[string]interface{}) error {
	title := "余额变更通知"
	content := fmt.Sprintf("您的账户发生%s，金额：%s %s，当前余额：%s %s", changeType, amount, currency, newBalance, currency)

	data := map[string]interface{}{
		"change_type": changeType,
		"amount":      amount,
		"currency":    currency,
		"new_balance": newBalance,
		"timestamp":   time.Now().Format("2006-01-02 15:04:05"),
	}

	// 合并额外数据
	if additionalData != nil {
		for k, v := range additionalData {
			data[k] = v
		}
	}

	return s.PublishSystemNotification(ctx, userID, title, content, data)
}

// GetAllNotificationTypes 获取所有通知类型
func (s *NotificationService) GetAllNotificationTypes(ctx context.Context) ([]models.NotificationType, error) {
	var notificationTypes []models.NotificationType
	err := s.db.WithContext(ctx).Find(&notificationTypes).Error
	if err != nil {
		return nil, fmt.Errorf("获取通知类型列表失败: %v", err)
	}
	return notificationTypes, nil
}
